package safecontainer

import (
	"runtime"
	"sync/atomic"
)

// SafeListTNode 节点
type SafeListTNode[T any] struct {
	next  atomic.Pointer[SafeListTNode[T]]
	value T
}

// func newNodeT[T any](data T) *SafeListTNode[T] {
// 	md := new(SafeListTNode[T])
// 	// md.next = &atomic.Pointer[SafeListTTNode]{}
// 	md.value = data
// 	return md
// 	// return unsafe.Pointer(&SafeListTTNode{
// 	// 	nil,
// 	// 	data,
// 	// })
// }

// SafeListT 安全链表
type SafeListT[T any] struct {
	head atomic.Pointer[SafeListTNode[T]]
	tail atomic.Pointer[SafeListTNode[T]]

	C chan bool

	vnil T
	// // 节点的池子
	// poolNode sync.Pool
}

// NewSafeListT 新创建一个列表
/*
给一个nil值对象进来
*/
func NewSafeListT[T any]() *SafeListT[T] {

	// node := newNodeT[T](vnil)
	result := &SafeListT[T]{
		// head: &atomic.Pointer[SafeListTTNode]{},
		// tail: &atomic.Pointer[SafeListTTNode]{},
		C: make(chan bool, 1),
		// poolNode: sync.Pool{New: func() any {
		// 	return new(SafeListTNode[T])
		// }},
	}
	node := new(SafeListTNode[T]) //result.poolNode.Get().(*SafeListTNode[T])
	result.head.Store(node)
	result.tail.Store(node)
	return result
}

func (sl *SafeListT[T]) newNode(data T) (result *SafeListTNode[T]) {
	result = new(SafeListTNode[T])
	// result = sl.poolNode.Get().(*SafeListTNode[T])
	result.value = data
	return
}

// Put 放入
func (sl *SafeListT[T]) Put(data T) {
	// newNodeT := newNodeT(data)
	newNodeT := sl.newNode(data)
	var tail *SafeListTNode[T]

	for {
		tail = sl.tail.Load()
		next := tail.next.Load() //atomic.LoadPointer(&(*SafeListTTNode)(tail).next)

		if next != nil {
			sl.tail.CompareAndSwap(tail, next)
			// atomic.CompareAndSwapPointer(&sl.tail, tail, next)
		} else {
			if sl.tail.Load().next.CompareAndSwap(nil, newNodeT) {
				break
			}
			// if atomic.CompareAndSwapPointer(&(*SafeListTTNode)(atomic.LoadPointer(&sl.tail)).next, nil, newNodeT) {
			// 	break
			// }
		}
		runtime.Gosched()
	}
	sl.tail.CompareAndSwap(tail, newNodeT)
	// atomic.CompareAndSwapPointer(&sl.tail, tail, newNodeT)

	select {
	case sl.C <- true:
	default:
	}
	// if len(sl.C) == 0 {
	// 	sl.C <- true
	// }
}

// var errNoNode = errors.New("no node")

// Pop 拿出
func (sl *SafeListT[T]) Pop() (result T, err error) {

	for {
		head := sl.head.Load()
		tail := sl.tail.Load()
		// head := atomic.LoadPointer(&sl.head)
		// tail := atomic.LoadPointer(&sl.tail)

		next := head.next.Load()
		// next := atomic.LoadPointer(&(*SafeListTTNode)(head).next)

		if head == tail {
			if next == nil {
				return sl.vnil, errNoNode
			}
			sl.tail.CompareAndSwap(tail, next)
			// atomic.CompareAndSwapPointer(&sl.tail, tail, next)
		} else {
			if sl.head.CompareAndSwap(head, next) {
				result = next.value
				next.value = sl.vnil
				// head.next.Store(nil)
				// head.value = sl.vnil
				// sl.poolNode.Put(head)
				return result, nil
			}
			// if atomic.CompareAndSwapPointer(&sl.head, head, next) {
			// 	n := (*SafeListTTNode)(next).value
			// 	(*SafeListTTNode)(next).value = nil
			// 	return n, nil
			// }
		}
		runtime.Gosched()
	}

}

// func (sl *SafeListT) Get() (interface{}, error) {
// 	head := atomic.LoadPointer(&sl.head)
// 	tail := atomic.LoadPointer(&sl.tail)

// 	next := atomic.LoadPointer(&(*SafeListTTNode)(head).next)

// 	if head == tail {
// 		if next == nil {
// 			return nil, errNoNode
// 		} else {
// 			return (*SafeListTTNode)(next).value, nil
// 		}
// 	} else {
// 		return (*SafeListTTNode)(next).value, nil
// 	}
// }

// IsEmpty 是否为空
func (sl *SafeListT[T]) IsEmpty() bool {
	head := sl.head.Load()
	tail := sl.tail.Load()
	// head := atomic.LoadPointer(&sl.head)
	// tail := atomic.LoadPointer(&sl.tail)

	next := head.next.Load()
	// next := atomic.LoadPointer(&(*SafeListTTNode)(head).next)
	if head == tail {
		if next == nil {
			return true
		}
	}

	return false
}
